package com.mhy.glide;

import android.content.Context;
import android.support.rastermill.FrameSequenceDrawable;
import android.util.Log;

import androidx.annotation.NonNull;

import com.bumptech.glide.Glide;
import com.bumptech.glide.GlideBuilder;
import com.bumptech.glide.Registry;
import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.load.DecodeFormat;
import com.bumptech.glide.load.engine.cache.DiskLruCacheFactory;
import com.bumptech.glide.load.engine.cache.ExternalPreferredCacheDiskCacheFactory;
import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.module.AppGlideModule;
import com.bumptech.glide.request.RequestOptions;
import com.mhy.glide.giflib.MyGifDecoder;
import com.mhy.glide.progress.OkHttpGlideUrlLoader;
import com.mhy.glide.progress.ProgressInterceptor;

import java.io.File;
import java.io.InputStream;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import okhttp3.OkHttpClient;

/**
 * Created By Mahongyin
 * Date    2020/8/24 10:03
 */
@GlideModule
public class MyGlideModule extends AppGlideModule {
    private static final String GLIDE_CACHE_DIR = "imageCache";
    private static long GLIDE_CACHE_SIZE = 1024 * 1024 * 60;

    @Override
    public boolean isManifestParsingEnabled() {
//        return super.isManifestParsingEnabled();
        return false; //防止重复 xml里的<data-meta>
    }

    //    @Override
//    public void registerComponents(Context context, Glide glide) {
//        /**
//         * 不带拦截功能，只是单纯替换通讯组件
//         */
//        //glide.register(GlideUrl.class, InputStream.class, new OkHttpGlideUrlLoader.Factory());
//
//        OkHttpClient.Builder builder = new OkHttpClient.Builder();
//        builder.addInterceptor(new ProgressInterceptor());
//        OkHttpClient okHttpClient = builder.build();
//        glide.register(GlideUrl.class, InputStream.class, new OkHttpGlideUrlLoader.Factory(okHttpClient));
//    }
    @Override
    public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
        super.registerComponents(context, glide, registry);
        /**
         * 不带拦截功能，只是单纯替换通讯组件
         */
        //定制OkHttp // 替换底层网络框架为okhttp3
//        OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
//        //请求头设置
//        httpClientBuilder.interceptors().add(new HeadInterceptor());//添加请求头
//        httpClientBuilder.addInterceptor(new ProgressInterceptor());//加载进度拦截
//        OkHttpClient okHttpClient = httpClientBuilder.build();

        OkHttpClient okHttpClient = getUnsafeOkHttpClient();//信任所有证书
        //替换->okhttp
        registry.replace(GlideUrl.class, InputStream.class,
                new OkHttpGlideUrlLoader.Factory(okHttpClient));

        // 添加一个 GifResourceDecoder, 用于将 GIF 的 InputStream 转为 FrameSequenceDrawable  这个还可以做播放Webp动画。
        registry.append(Registry.BUCKET_GIF, InputStream.class,
                FrameSequenceDrawable.class, new MyGifDecoder(glide.getBitmapPool()));
    }

    /**
     * setMemoryCache()
     * 用于配置Glide的内存缓存策略，默认配置是LruResourceCache。
     * <p>
     * setBitmapPool()
     * 用于配置Glide的Bitmap缓存池，默认配置是LruBitmapPool。
     * <p>
     * setDiskCache()
     * 用于配置Glide的硬盘缓存策略，默认配置是InternalCacheDiskCacheFactory。
     * <p>
     * setDiskCacheService()
     * 用于配置Glide读取缓存中图片的异步执行器，默认配置是FifoPriorityThreadPoolExecutor，
     * 也就是先入先出原则。
     * <p>
     * setResizeService()
     * 用于配置Glide读取非缓存中图片的异步执行器，默认配置也是FifoPriorityThreadPoolExecutor。
     * <p>
     * setDecodeFormat()
     * 用于配置Glide加载图片的解码模式，默认配置是RGB_565。
     */
    //缓存
    @Override
    public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) {
        super.applyOptions(context, builder);

//        File cacheFilesDir = context.getExternalFilesDir(null);//是在sdcard/imageCache目录当中
        File cacheFilesDir = context.getCacheDir();
        /*sdcard/Android/data/包名/cache/imageCache目录当中*/
        if (cacheFilesDir != null) {
            String diskCacheFolder = cacheFilesDir.getAbsolutePath();
            Log.e("TAG", "diskCacheFolder->" + diskCacheFolder);
            builder.setDiskCache(
                    new DiskLruCacheFactory(diskCacheFolder, GLIDE_CACHE_DIR, GLIDE_CACHE_SIZE));
            builder.setDefaultRequestOptions(
                    new RequestOptions().format(DecodeFormat.PREFER_ARGB_8888));
        } else {
            Log.e("TAG", "null->");
            //自定义缓存目录
//            builder.setDiskCache(new InternalCacheDiskCacheFactory(context, GLIDE_CACHE_DIR, GLIDE_CACHE_SIZE));
            /* 更改缓存最总文件夹名称 ExternalCacheDiskCacheFactory是在sdcard/Android/data/包名/cache/imageCache目录当中*/
            builder.setDiskCache(
                    new ExternalPreferredCacheDiskCacheFactory(context, GLIDE_CACHE_DIR,
                            GLIDE_CACHE_SIZE));
          //  builder.setMemoryCache()
            //全局设置图片格式为RGB_565 非ARGB8888  DecodeFormat.PREFER_ARGB_8888 虽然图片质量变好了，但同时内存开销也会明显增大
            builder.setDefaultRequestOptions(
                    new RequestOptions().format(DecodeFormat.PREFER_RGB_565));
        }
    }

    //Glide信任okhttp所有证书
    public static OkHttpClient getUnsafeOkHttpClient() {
        try {
            // Create a trust manager that does not validate certificate chains
            final TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509TrustManager() {
                        @Override
                        public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType)
                                throws CertificateException {
                        }

                        @Override
                        public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType)
                                throws CertificateException {
                        }

                        @Override
                        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                            return new X509Certificate[]{};
                        }
                    }
            };

            // Install the all-trusting trust manager
            final SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
            // Create an ssl socket factory with our all-trusting manager
            final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
            OkHttpClient.Builder builder = new OkHttpClient.Builder();
            builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]);
            builder.hostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    return true;//始终通过
                }
            });
            builder.connectTimeout(10, TimeUnit.SECONDS);
            builder.readTimeout(10, TimeUnit.SECONDS);
//            builder.interceptors().add(new HeadInterceptor(null));//添加请求头
            builder.addInterceptor(new ProgressInterceptor());//加载进度拦截
            return builder.build();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    //如果没替换okhttp 信任所有证书 Glide默认HttpsURLConnection      APPlication中调
    private void handleSSLHandshake() {
        try {
            TrustManager[] trustAllCerts =
                    new TrustManager[]{new X509TrustManager() {
                        @Override
                        public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {

                        }

                        @Override
                        public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {

                        }

                        @Override
                        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                            return new X509Certificate[0];
                        }
                    }};
            SSLContext sc = SSLContext.getInstance("TLS");
            // trustAllCerts信任所有的证书
            sc.init(null, trustAllCerts, new SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
            HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });
        } catch (Exception ignored) {
        }
    }

}
